package cmd

import (
	"fmt"
	"os"
	"time"

	"sysinfo/internal/collector"
	"sysinfo/internal/config"
	"sysinfo/internal/formatter"

	"github.com/spf13/cobra"
)

var cfg *config.Config
var configFile string

var rootCmd = &cobra.Command{
	Use:   "系统工具",
	Short: "系统信息收集和处理工具（目标兼容ios/android/macos）",
	Long:  `一个跨平台的系统信息收集工具，能够获取系统、CPU、内存、磁盘、网络、进程、SMART数据等信息。`,
	RunE:  runSysInfo,
}

func init() {
	cfg = config.NewConfig()

	// 配置文件
	rootCmd.PersistentFlags().StringVar(&configFile, "config", "", "配置文件 (默认: 搜索 .sysinforc, ~/.config/sysinfo/config.yaml)")

	// 输出选项
	rootCmd.Flags().StringVarP(&cfg.Format, "format", "f", "pretty", "输出格式: json, text, pretty, table")
	rootCmd.Flags().StringVarP(&cfg.OutputFile, "output", "o", "", "输出文件路径 (默认: 标准输出)")
	rootCmd.Flags().BoolVarP(&cfg.Verbose, "verbose", "v", false, "详细输出")

	// 完整转储模式
	rootCmd.Flags().BoolVar(&cfg.FullDumpToFile, "full-dump", false, "收集所有系统信息并保存到 sysinfo_dump.json")

	// 轮询监控模式
	rootCmd.Flags().BoolVar(&cfg.Stream, "stream", false, "启用轮询监控模式，持续收集系统信息")
	rootCmd.Flags().IntVar(&cfg.StreamInterval, "interval", 5, "轮询间隔时间（秒）")

	// API模式
	rootCmd.Flags().BoolVar(&cfg.API, "api", false, "启用API服务器模式，提供HTTP JSON接口")
	rootCmd.Flags().IntVar(&cfg.APIPort, "port", 8000, "API服务器端口")

	// 模块选择标志
	rootCmd.Flags().BoolVar(&cfg.Modules.All, "all", true, "收集所有信息")
	rootCmd.Flags().BoolVar(&cfg.Modules.System, "system", false, "收集系统信息")
	rootCmd.Flags().BoolVar(&cfg.Modules.CPU, "cpu", false, "收集CPU信息")
	rootCmd.Flags().BoolVar(&cfg.Modules.Memory, "memory", false, "收集内存信息")
	rootCmd.Flags().BoolVar(&cfg.Modules.Disk, "disk", false, "收集磁盘信息")
	rootCmd.Flags().BoolVar(&cfg.Modules.Network, "network", false, "收集网络信息")
	rootCmd.Flags().BoolVar(&cfg.Modules.Ports, "ports", false, "收集端口占用信息")
	rootCmd.Flags().BoolVar(&cfg.Modules.Process, "process", false, "收集进程信息")
	rootCmd.Flags().BoolVar(&cfg.Modules.SMART, "smart", false, "收集SMART磁盘数据 (可能需要提升权限)")
	rootCmd.Flags().BoolVar(&cfg.Modules.GPU, "gpu", false, "收集GPU信息")
	rootCmd.Flags().BoolVar(&cfg.Modules.Battery, "battery", false, "收集电池信息")
	rootCmd.Flags().BoolVar(&cfg.Modules.Activity, "activity", false, "收集最近操作与浏览过的文件（仅Windows，macos/linux需要测试，应该ok的）")
	rootCmd.Flags().IntSliceVar(&cfg.Modules.KillPorts, "kill-ports", nil, "端口查杀：终止占用指定端口的进程 (可能需要提升权限)，示例: --kill-ports 80,443,8080")

}

func Execute() error {
	return rootCmd.Execute()
}

func runSysInfo(cmd *cobra.Command, args []string) error {
	// 加载配置文件（如果存在）
	fileConfig, err := config.LoadConfigFile(configFile)
	if err != nil {
		return fmt.Errorf("加载配置文件失败: %w", err)
	}

	// 合并文件配置与CLI标志（CLI优先）
	cfg.MergeWithFileConfig(fileConfig)

	// 处理API服务器模式
	if cfg.API {
		return runAPIServer()
	}

	// 处理轮询监控模式
	if cfg.Stream {
		return runStreamMode()
	}

	// 处理完整转储模式
	if cfg.FullDumpToFile {
		return runFullDump()
	}

	// 如果选择了特定模块或提供了 --kill-ports，禁用 --all
	anySelected := anyModuleSelected(cfg.Modules)
	if anySelected || len(cfg.Modules.KillPorts) > 0 {
		cfg.Modules.All = false
	}
	// 端口查杀（如果提供了 --kill-ports）
	if len(cfg.Modules.KillPorts) > 0 {
		vprintf("正在查杀端口: %v\n", cfg.Modules.KillPorts)
		killed, failed, kerr := collector.KillProcessesByPorts(cfg.Modules.KillPorts)
		if kerr != nil {
			return fmt.Errorf("端口查杀失败: %w", kerr)
		}
		if len(killed) > 0 {
			fmt.Fprintf(os.Stderr, "已终止进程: %v\n", killed)
		}
		if len(failed) > 0 {
			fmt.Fprintf(os.Stderr, "以下进程终止失败（可能需要提升权限）：\n")
			for pid, e := range failed {
				fmt.Fprintf(os.Stderr, "  PID %d: %v\n", pid, e)
			}
		}

		// 如果仅提供了 --kill-ports 且未选择任何模块，直接退出，不进行后续收集
		if !anySelected {
			vprintf("已执行端口查杀，未选择模块，跳过信息收集。\n")
			return nil
		}
	}

	vprintf("正在收集系统信息...\n")

	// 收集系统信息
	info, err := collector.Collect(cfg)
	if err != nil {
		return fmt.Errorf("收集系统信息失败: %w", err)
	}

	vprintf("正在格式化输出...\n")

	// 格式化输出
	output, err := formatter.Format(info, cfg)
	if err != nil {
		return fmt.Errorf("格式化输出失败: %w", err)
	}

	// 写入输出
	if cfg.OutputFile != "" {
		if cfg.Verbose {
			fmt.Fprintf(os.Stderr, "正在写入文件: %s\n", cfg.OutputFile)
		}
		err = os.WriteFile(cfg.OutputFile, []byte(output), 0644)
		if err != nil {
			return fmt.Errorf("写入输出文件失败: %w", err)
		}
		fmt.Fprintf(os.Stderr, "输出已写入: %s\n", cfg.OutputFile)
	} else {
		fmt.Print(output)
	}

	// 检查是否应该暂停（当双击运行时，不是从终端运行）
	waitForEnter()

	return nil
}

// runFullDump 收集所有可能的系统信息并保存到JSON文件
func runFullDump() error {

	fmt.Fprintf(os.Stderr, "开始收集全面的系统信息转储...\n")
	fmt.Fprintf(os.Stderr, "这将收集所有可用数据（可能需要一些时间）...\n\n")

	// 创建配置以收集所有信息
	dumpConfig := config.NewConfig()
	dumpConfig.Modules.All = true
	dumpConfig.Format = "json"

	fmt.Fprintf(os.Stderr, "✓ 正在收集系统信息...\n")
	info, err := collector.Collect(dumpConfig)
	if err != nil {
		return fmt.Errorf("收集系统信息失败: %w", err)
	}

	fmt.Fprintf(os.Stderr, "✓ 正在格式化为JSON数据...\n")
	output, err := formatter.Format(info, dumpConfig)
	if err != nil {
		return fmt.Errorf("格式化输出失败: %w", err)
	}

	// 确定输出文件名（在可执行文件旁边）
	filename := "sysinfo_dump.json"

	fmt.Fprintf(os.Stderr, "✓ 正在写入文件: %s\n", filename)
	err = os.WriteFile(filename, []byte(output), 0644)
	if err != nil {
		return fmt.Errorf("写入转储文件失败: %w", err)
	}

	fileInfo, _ := os.Stat(filename)
	sizeKB := float64(fileInfo.Size()) / 1024.0
	sizeMB := sizeKB / 1024.0

	fmt.Fprintf(os.Stderr, "\n")
	fmt.Fprintf(os.Stderr, "═══════════════════════════════════════════════════════════════\n")
	fmt.Fprintf(os.Stderr, "  完整系统转储已完成\n")
	fmt.Fprintf(os.Stderr, "═══════════════════════════════════════════════════════════════\n")
	fmt.Fprintf(os.Stderr, "  文件: %s\n", filename)
	if sizeMB >= 1.0 {
		fmt.Fprintf(os.Stderr, "  大小: %.2f MB\n", sizeMB)
	} else {
		fmt.Fprintf(os.Stderr, "  大小: %.2f KB\n", sizeKB)
	}
	fmt.Fprintf(os.Stderr, "\n")
	fmt.Fprintf(os.Stderr, "  包含内容:\n")
	fmt.Fprintf(os.Stderr, "    • 系统信息\n")
	fmt.Fprintf(os.Stderr, "    • 详细的CPU数据\n")
	fmt.Fprintf(os.Stderr, "    • 内存信息和物理模块\n")
	fmt.Fprintf(os.Stderr, "    • 磁盘分区和物理磁盘\n")
	fmt.Fprintf(os.Stderr, "    • 网络接口和统计信息\n")
	fmt.Fprintf(os.Stderr, "    • 进程信息\n")
	fmt.Fprintf(os.Stderr, "    • 全面的SMART数据和健康状况评估\n")
	fmt.Fprintf(os.Stderr, "    • GPU信息\n")
	fmt.Fprintf(os.Stderr, "═══════════════════════════════════════════════════════════════\n")
	fmt.Fprintf(os.Stderr, "\n")

	// 暂停以便用户在双击时能看到结果
	waitForEnter()

	return nil
}

// runStreamMode 轮询监控模式 - 定时收集和输出系统信息
func runStreamMode() error {
	if cfg.StreamInterval < 1 {
		cfg.StreamInterval = 5 // 最小间隔1秒，默认5秒
	}

	fmt.Fprintf(os.Stderr, "═══════════════════════════════════════════════════════════════\n")
	fmt.Fprintf(os.Stderr, "  轮询监控模式已启动\n")
	fmt.Fprintf(os.Stderr, "═══════════════════════════════════════════════════════════════\n")
	fmt.Fprintf(os.Stderr, "  轮询间隔: %d 秒\n", cfg.StreamInterval)
	fmt.Fprintf(os.Stderr, "  输出格式: %s\n", cfg.Format)
	fmt.Fprintf(os.Stderr, "  收集模块: ")

	if cfg.Modules.All {
		fmt.Fprintf(os.Stderr, "全部模块\n")
	} else {
		modules := []string{}
		if cfg.Modules.System {
			modules = append(modules, "系统")
		}
		if cfg.Modules.CPU {
			modules = append(modules, "CPU")
		}
		if cfg.Modules.Memory {
			modules = append(modules, "内存")
		}
		if cfg.Modules.Disk {
			modules = append(modules, "磁盘")
		}
		if cfg.Modules.Network {
			modules = append(modules, "网络")
		}
		if cfg.Modules.Process {
			modules = append(modules, "进程")
		}
		if cfg.Modules.SMART {
			modules = append(modules, "SMART")
		}
		if cfg.Modules.GPU {
			modules = append(modules, "GPU")
		}
		if cfg.Modules.Battery {
			modules = append(modules, "电池")
		}
		if cfg.Modules.Activity {
			modules = append(modules, "最近活动")
		}

		if len(modules) > 0 {
			for i, module := range modules {
				if i > 0 {
					fmt.Fprintf(os.Stderr, ", ")
				}
				fmt.Fprintf(os.Stderr, "%s", module)
			}
			fmt.Fprintf(os.Stderr, "\n")
		} else {
			fmt.Fprintf(os.Stderr, "无（将使用全部模块）\n")
		}
	}
	fmt.Fprintf(os.Stderr, "═══════════════════════════════════════════════════════════════\n")
	fmt.Fprintf(os.Stderr, "\n")
	fmt.Fprintf(os.Stderr, "按 Ctrl+C 停止监控\n\n")

	counter := 0
	for {
		counter++

		if cfg.Verbose {
			fmt.Fprintf(os.Stderr, "\n【第 %d 次收集 - %s】\n", counter, time.Now().Format("2006-01-02 15:04:05"))
		}

		// 收集系统信息
		info, err := collector.Collect(cfg)
		if err != nil {
			fmt.Fprintf(os.Stderr, "错误: 收集系统信息失败: %v\n", err)
			time.Sleep(time.Duration(cfg.StreamInterval) * time.Second)
			continue
		}

		// 格式化输出
		output, err := formatter.Format(info, cfg)
		if err != nil {
			fmt.Fprintf(os.Stderr, "错误: 格式化输出失败: %v\n", err)
			time.Sleep(time.Duration(cfg.StreamInterval) * time.Second)
			continue
		}

		// 输出结果
		if cfg.OutputFile != "" {
			// 文件输出模式 - 追加写入
			file, err := os.OpenFile(cfg.OutputFile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
			if err != nil {
				fmt.Fprintf(os.Stderr, "错误: 打开输出文件失败: %v\n", err)
			} else {
				defer file.Close()

				// 添加时间戳分隔符
				timestamp := time.Now().Format("2006-01-02 15:04:05")
				separator := fmt.Sprintf("\n\n═══════════════════════════════════════════════════════════════\n")
				separator += fmt.Sprintf("  收集时间: %s\n", timestamp)
				separator += fmt.Sprintf("═══════════════════════════════════════════════════════════════\n\n")

				if _, err := file.WriteString(separator + output); err != nil {
					fmt.Fprintf(os.Stderr, "错误: 写入文件失败: %v\n", err)
				} else {
					fmt.Fprintf(os.Stderr, "✓ 第 %d 次数据已写入: %s\n", counter, cfg.OutputFile)
				}
			}
		} else {
			// 标准输出
			if cfg.Format == "json" && counter > 1 {
				// JSON格式需要特殊处理，添加逗号分隔
				fmt.Print(",")
			}
			fmt.Print(output)
		}

		// 等待下一次轮询
		time.Sleep(time.Duration(cfg.StreamInterval) * time.Second)
	}
}

// waitForEnter 暂停并等待用户输入（当不是从终端运行时）
func waitForEnter() {
	// 在Windows上，检查是否从资源管理器运行（没有附加终端）
	// 这有助于当.exe被双击时
	if !isTerminal() {
		fmt.Println("\n按Enter键退出...")
		if _, err := fmt.Scanln(); err != nil {
			fmt.Fprintf(os.Stderr, "输入错误: %v\n", err)
		}
	}
}

// isTerminal 检查stdout是否连接到终端
func isTerminal() bool {
	fileInfo, err := os.Stdout.Stat()
	if err != nil {
		return false
	}
	// 检查是否为字符设备（终端）
	return (fileInfo.Mode() & os.ModeCharDevice) != 0
}

// vprintf 在开启 verbose 时输出到标准错误
func vprintf(format string, args ...interface{}) {
	if cfg != nil && cfg.Verbose {
		fmt.Fprintf(os.Stderr, format, args...)
	}
}

// anyModuleSelected 返回是否选择了任意单个模块（不含 All）
func anyModuleSelected(m config.ModuleConfig) bool {
	return m.System || m.CPU || m.Memory ||
		m.Disk || m.Network || m.Ports || m.Process || m.SMART || m.GPU || m.Battery || m.Activity
}
